<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Parallel array</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Parallel_array"> <link href="./mw/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Parallel_array rootpage-Parallel_array skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Parallel array</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr"><p>In <a href="Computing" title="Computing">computing</a>, a group of <b>parallel arrays</b> (also known as <a href="Structure_of_arrays" class="mw-redirect" title="Structure of arrays">structure of arrays</a> or SoA) is a form of <a href="Implicit_data_structure" title="Implicit data structure">implicit data structure</a> that uses multiple <a href="Array_data_structure" class="mw-redirect" title="Array data structure">arrays</a> to represent a singular array of <a href="Record_(computer_science)" title="Record (computer science)">records</a>. It keeps a separate, homogeneous data array for each field of the record, each having the same number of elements. Then, objects located at the same index in each array are implicitly the fields of a single record. Pointers from one object to another are replaced by array indices. This contrasts with the normal approach of storing all fields of each record together in memory (also known as <a href="Array_of_structures" class="mw-redirect" title="Array of structures">array of structures</a> or AoS). For example, one might declare an array of 100 names, each a string, and 100 ages, each an integer, associating each name with the age that has the same index.
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="Examples">Examples</h2></div>
<p>An example in <a href="C_(programming_language)" title="C (programming language)">C</a> using parallel arrays:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span class="kt">int</span><span class="w"> </span><span class="n">ages</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">17</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">52</span><span class="p">,</span><span class="w"> </span><span class="mi">25</span><span class="p">};</span>
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">names</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">"None"</span><span class="p">,</span><span class="w"> </span><span class="s">"Mike"</span><span class="p">,</span><span class="w"> </span><span class="s">"Billy"</span><span class="p">,</span><span class="w"> </span><span class="s">"Tom"</span><span class="p">,</span><span class="w"> </span><span class="s">"Stan"</span><span class="p">};</span>
<span class="kt">int</span><span class="w"> </span><span class="n">parent</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="w"> </span><span class="cm">/*None*/</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="cm">/*Tom*/</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="cm">/*Mike*/</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="cm">/*None*/</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="cm">/*Tom*/</span><span class="p">};</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Name: %s, Age: %d, Parent: %s </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="w"> </span><span class="n">names</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">ages</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">names</span><span class="p">[</span><span class="n">parent</span><span class="p">[</span><span class="n">i</span><span class="p">]]);</span>
<span class="p">}</span>
</pre></div>
<p>in <a href="Perl" title="Perl">Perl</a> (using a hash of arrays to hold references to each array):
</p>
<div class="mw-highlight mw-highlight-lang-perl mw-content-ltr" dir="ltr"><pre><span class="k">my</span><span class="w"> </span><span class="nv">%data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w"> </span><span class="n">first_name</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">[</span><span class="s">'Joe'</span><span class="p">,</span><span class="w"> </span><span class="s">'Bob'</span><span class="p">,</span><span class="w"> </span><span class="s">'Frank'</span><span class="p">,</span><span class="w"> </span><span class="s">'Hans'</span><span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="n">last_name</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">[</span><span class="s">'Smith'</span><span class="p">,</span><span class="s">'Seger'</span><span class="p">,</span><span class="s">'Sinatra'</span><span class="p">,</span><span class="s">'Schultze'</span><span class="p">],</span>
<span class="w"> </span><span class="n">height_in_cm</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">[</span><span class="mi">169</span><span class="p">,</span><span class="w"> </span><span class="mi">158</span><span class="p">,</span><span class="w"> </span><span class="mi">201</span><span class="p">,</span><span class="w"> </span><span class="mi">199</span><span class="w"> </span><span class="p">]);</span>
<span class="k">for</span><span class="w"> </span><span class="nv">$i</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="nv">$#</span><span class="p">{</span><span class="nv">$data</span><span class="p">{</span><span class="n">first_name</span><span class="p">}})</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">printf</span><span class="w"> </span><span class="s">"Name: %s %s\n"</span><span class="p">,</span><span class="w"> </span><span class="nv">$data</span><span class="p">{</span><span class="n">first_name</span><span class="p">}[</span><span class="nv">$i</span><span class="p">],</span><span class="w"> </span><span class="nv">$data</span><span class="p">{</span><span class="n">last_name</span><span class="p">}[</span><span class="nv">$i</span><span class="p">];</span>
<span class="w"> </span><span class="nb">printf</span><span class="w"> </span><span class="s">"Height in CM: %i\n"</span><span class="p">,</span><span class="w"> </span><span class="nv">$data</span><span class="p">{</span><span class="n">height_in_cm</span><span class="p">}[</span><span class="nv">$i</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>
<p>Or, in <a href="Python_Programming_Language" class="mw-redirect" title="Python Programming Language">Python</a>:
</p>
<div class="mw-highlight mw-highlight-lang-python3 mw-content-ltr" dir="ltr"><pre><span class="n">first_names</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Joe"</span><span class="p">,</span> <span class="s2">"Bob"</span><span class="p">,</span> <span class="s2">"Frank"</span><span class="p">,</span> <span class="s2">"Hans"</span> <span class="p">]</span>
<span class="n">last_names</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Smith"</span><span class="p">,</span><span class="s2">"Seger"</span><span class="p">,</span><span class="s2">"Sinatra"</span><span class="p">,</span><span class="s2">"Schultze"</span><span class="p">]</span>
<span class="n">heights_in_cm</span> <span class="o">=</span> <span class="p">[</span><span class="mi">169</span><span class="p">,</span> <span class="mi">158</span><span class="p">,</span> <span class="mi">201</span><span class="p">,</span> <span class="mi">199</span> <span class="p">]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">first_names</span><span class="p">)):</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Name: </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">first_names</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">last_names</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">"Height in cm: </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">heights_in_cm</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<span class="c1"># Using zip:</span>
<span class="k">for</span> <span class="n">first_name</span><span class="p">,</span> <span class="n">last_name</span><span class="p">,</span> <span class="n">height_in_cm</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">first_names</span><span class="p">,</span> <span class="n">last_names</span><span class="p">,</span> <span class="n">heights_in_cm</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Name: </span><span class="si">{</span><span class="n">first_name</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">last_name</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Height in cm: </span><span class="si">{</span><span class="n">height_in_cm</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Pros_and_cons">Pros and cons</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1251242444">
/* start https://en.wikipedia.org/ */
.mw-parser-output .ambox{border:1px solid #a2a9b1;border-left:10px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .ambox+link+.ambox,.mw-parser-output .ambox+link+style+.ambox,.mw-parser-output .ambox+link+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+style+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+link+.ambox{margin-top:-1px}html body.mediawiki .mw-parser-output .ambox.mbox-small-left{margin:4px 1em 4px 0;overflow:hidden;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.mw-parser-output .ambox-speedy{border-left:10px solid #b32424;background-color:#fee7e6}.mw-parser-output .ambox-delete{border-left:10px solid #b32424}.mw-parser-output .ambox-content{border-left:10px solid #f28500}.mw-parser-output .ambox-style{border-left:10px solid #fc3}.mw-parser-output .ambox-move{border-left:10px solid #9932cc}.mw-parser-output .ambox-protection{border-left:10px solid #a2a9b1}.mw-parser-output .ambox .mbox-text{border:none;padding:0.25em 0.5em;width:100%}.mw-parser-output .ambox .mbox-image{border:none;padding:2px 0 2px 0.5em;text-align:center}.mw-parser-output .ambox .mbox-imageright{border:none;padding:2px 0.5em 2px 0;text-align:center}.mw-parser-output .ambox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .ambox .mbox-image-div{width:52px}@media(min-width:720px){.mw-parser-output .ambox{margin:0 10%}}@media print{body.ns-0 .mw-parser-output .ambox{display:none!important}}
/* end https://en.wikipedia.org/ */
</style>
<p>Parallel arrays have a number of practical advantages over the normal approach:
</p>
<ul><li>They can save a substantial amount of space in some cases by avoiding alignment issues. For example, some architectures work best if 4-byte integers are always stored beginning at memory locations that are multiple of 4. If the previous field was a single byte, 3 bytes might be wasted. Many modern compilers can automatically avoid such problems, though in the past some programmers would explicitly declare fields in order of decreasing alignment restrictions.</li>
<li>If the number of items is small, array indices can occupy significantly less space than full pointers, particularly on some architectures.</li>
<li>Sequentially examining a single field of each record in the array is very fast on modern machines, since this amounts to a linear traversal of a single array, exhibiting ideal <a href="Locality_of_reference" title="Locality of reference">locality of reference</a> and cache behaviour.</li>
<li>They may allow efficient processing with <a href="SIMD_instruction" class="mw-redirect" title="SIMD instruction">SIMD instructions</a> in certain <a href="Instruction_set_architecture" title="Instruction set architecture">instruction set architectures</a></li></ul>
<p>Several of these advantages depend strongly on the particular programming language and implementation in use.
</p><p>However, parallel arrays also have several strong disadvantages, which serves to explain why they are not generally preferred:
</p>
<ul><li>They have significantly worse <a href="Locality_of_reference" title="Locality of reference">locality of reference</a> when visiting the records non-sequentially and examining multiple fields of each record, because the various arrays may be stored arbitrarily far apart.</li>
<li>They obscure the relationship between fields of a single record (e.g. no type information relates the index between them, an index may be used erroneously).</li>
<li>They have little direct language support (the language and its syntax typically express no relationship between the arrays in the parallel array, and cannot catch errors).</li>
<li>Since the bundle of fields is not a "thing", passing it around is tedious and error-prone. For example, rather than calling a function to do something to one record (or structure or object), the function must take the fields as separate arguments. When a new field is added or changed, many parameter lists must change, where passing objects as whole would avoid such changes entirely.</li>
<li>They are expensive to grow or shrink, since each of several arrays must be reallocated. Multi-level arrays can ameliorate this problem, but impacts performance due to the additional <a href="Indirection" title="Indirection">indirection</a> needed to find the desired elements.</li>
<li>Perhaps worst of all, they greatly raise the possibility of errors. Any insertion, deletion, or move must always be applied consistently to all of the arrays, or the arrays will no longer be synchronized with each other, leading to bizarre outcomes.</li></ul>
<p>The bad locality of reference can be alleviated in some cases: if a structure can be divided into groups of fields that are generally accessed together, an array can be constructed for each group, and its elements are records containing only these subsets of the larger structure's fields. (see <a href="Data-oriented_design" title="Data-oriented design">data-oriented design</a>). This is a valuable way of speeding up access to very large structures with many members, while keeping the portions of the structure tied together. An alternative to tying them together using array indexes is to use <a href="Reference_(computer_science)" title="Reference (computer science)">references</a> to tie the portions together, but this can be less efficient in time and space.
</p><p>Another alternative is to use a single array, where each entry is a record structure. Many language provide a way to declare actual records, and arrays of them. In other languages it may be feasible to simulate this by declaring an array of n*m size, where m is the size of all the fields together, packing the fields into what is effectively a record, even though the particular language lacks direct support for records. Some <a href="Compiler_optimization" class="mw-redirect" title="Compiler optimization">compiler optimizations</a>, particularly for <a href="Vector_processor" title="Vector processor">vector processors</a>, are able to perform this transformation automatically when arrays of structures are created in the program.
</p>
<div class="mw-heading mw-heading2"><h2 id="See_also">See also</h2></div>
<ul><li><a href="Linked_list#Linked_lists_using_arrays_of_nodes" title="Linked list">An example in the linked list article</a></li>
<li><a href="Column-oriented_DBMS" class="mw-redirect" title="Column-oriented DBMS">Column-oriented DBMS</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<ul><li><a href="Thomas_H._Cormen" title="Thomas H. Cormen">Thomas H. Cormen</a>, <a href="Charles_E._Leiserson" title="Charles E. Leiserson">Charles E. Leiserson</a>, <a href="Ronald_L._Rivest" class="mw-redirect" title="Ronald L. Rivest">Ronald L. Rivest</a>, and <a href="Clifford_Stein" title="Clifford Stein">Clifford Stein</a>. <i><a href="Introduction_to_Algorithms" title="Introduction to Algorithms">Introduction to Algorithms</a></i>, Second Edition. MIT Press and McGraw-Hill, 2001. <style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */
.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}
/* end https://en.wikipedia.org/ */
</style><a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a> <bdi>0-262-03293-7</bdi>. Page 209 of section 10.3: Implementing pointers and objects.</li>
<li><cite id="CITEREFSkeet2014" class="citation web cs1">Skeet, Jon (3 June 2014). <a rel="nofollow" class="external text" href="http://codeblog.jonskeet.uk/2014/06/03/anti-pattern-parallel-collections/">"Anti-pattern: parallel collections"</a><span class="reference-accessdate">. Retrieved <span class="nowrap">28 October</span> 2014</span>.</cite></li></ul></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2024-12-17" href="https://en.wikipedia.org/wiki/?title=Parallel_array&oldid=1263647666">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
</body></html>